#include <chrono>
#include <thread>

#include "lib/tools.h"
#include "lib/data_io.h"
#include "lib/init_solution.h"
#include "lib/optimizer_local.h"
#include "lib/optimizer_radical.h"
#include "lib/optimizer_center.h"
using namespace std;

void opt_solution(AssignInfo &assign_info)
{
    OptLocal local_optimizer(assign_info);
    OptRadical radical_optimizer(assign_info);
    OptCenter center_optimizer(assign_info);

    clock_t end_time;
    double edge_score = 0;
    double center_score = 0;
    double last_time_edge_score = 0;
    double last_time_center_score = 0;

    for (int i = 0; i < 500; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            last_time_center_score = center_score;
            center_score = center_optimizer.opt(0.945, 0.95, 0.946, 0.99, 20);
            if (last_time_center_score == center_score)
            {
                break;
            }
        }

        for (int j = 0; j < 30; j++)
        {
            last_time_edge_score = edge_score;
            edge_score = local_optimizer.opt(0.949, 0.95, 0.945, 0.95, false, false);
            if (last_time_edge_score == edge_score)
            {
                break;
            }
        }

        radical_optimizer.opt(0.949, 0.95, 0.945, 0.99, 1000);
        end_time = clock();
        double dur = (double)(end_time - STARTTIME);
        if (dur / CLOCKS_PER_SEC > 200)
        {
            break;
        }
    }

    for (int j = 0; j < 10; j++)
    {
        center_optimizer.opt(0.949, 0.95, 0.945, 0.95, 20);
    }

    for (int j = 0; j < 20; j++)
    {
        local_optimizer.opt(0.949, 0.95, 0.945, 0.95, false, false);
    }
}

int main()
{
    read_all_data();
    AssignInfo initial_solution = init_solution();

    opt_solution(initial_solution);

    check_solution(initial_solution);
    
    show_score(initial_solution);
    
    output(initial_solution);
}